package com.shfl.servermanage.exception;


import com.shfl.servermanage.common.ApiResultHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartException;

import java.lang.reflect.UndeclaredThrowableException;

/**
 * 全局异常处理器
 */
@ControllerAdvice
class GlobalExceptionHelper {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    protected static final String PARAMS_ERROR = "9100";
    protected static final String FILE_SIZE_LIMIT_ERROR = "9113";

    @ResponseBody
    @ExceptionHandler(ApiException.class)
    Object handle(ApiException e) {
        logger.error(e.getMessage());
        return new ApiResultHelper(e.resCode, e.resDesc);
    }

    @ResponseBody
    @ExceptionHandler(MissingServletRequestParameterException.class)
    Object handle(MissingServletRequestParameterException e) {
        logger.warn(e.getMessage());
        return new ApiResultHelper(PARAMS_ERROR);
    }

    @ResponseBody
    @ExceptionHandler(MultipartException.class)
    Object handle(MultipartException e) {
        logger.warn(e.getMessage());
        if (e instanceof MaxUploadSizeExceededException) {
            return new ApiResultHelper(FILE_SIZE_LIMIT_ERROR);
        }
        return new ApiResultHelper("9999");
    }

    @ResponseBody
    @ExceptionHandler(MethodArgumentNotValidException.class)
    Object handle(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        StringBuilder sb = new StringBuilder();
        for (ObjectError error : bindingResult.getAllErrors()) {
            FieldError fieldError = (FieldError) error;
            sb.append(fieldError.getField() + fieldError.getDefaultMessage());
        }
        logger.warn(sb.toString().join(";"));
        return new ApiResultHelper(PARAMS_ERROR);
    }

    @ResponseBody
    @ExceptionHandler(UndeclaredThrowableException.class)
    Object handle(UndeclaredThrowableException e) {
        Object ex = getRealException(e);
        if (ex instanceof ApiException) {
            return handle((ApiException) ex);
        } else {
            return handle((Exception) ex);
        }
    }

    @ResponseBody
    @ExceptionHandler(Exception.class)
    Object handle(Exception ex) {
        logger.error(ex.getMessage(), ex);
        return new ApiResultHelper("9999");
    }

    Exception getRealException(UndeclaredThrowableException e) {
        if (e == null) {
            return null;
        }
        Object cause = e.getCause();
        if (cause instanceof UndeclaredThrowableException) {
            return getRealException((UndeclaredThrowableException) cause);
        }
        return (Exception) cause;
    }
}
